// Copyright(c) Sonosemi Medical Ltd. Embedded Software Team.
// Author: Zhang Yisong(zhangyisong@sonosemi.com)

#pragma once
#include <chrono>
#include <etl/delegate.h>
#include <type_traits>
#if __has_include(<zephyr/kernel.h>)
#include <zephyr/kernel.h>
namespace active {

template <typename TEvent> struct Defer {
  LOG_MODULE("Defer Event");
  template <typename TChrono>
  static auto Publish(TChrono delay, etl::delegate<void()> delegate) {
    using namespace std::chrono;
    auto msec = duration_cast<milliseconds>(delay);
    if (const auto code = k_work_reschedule(&m_item, K_MSEC(msec.count())); code < 0) {
      LOG_ERROR("defer event [{}] failed, error code [{}]", TEvent::Name(), code);
    }
  }
  Defer() { k_work_init_delayable(&m_item, WqHandler); }
  inline static k_work_delayable m_item;
  static auto WqHandler(k_work *item) -> void { TEvent::Publish(); }
};

} // namespace active
#endif

#include "active/active_event.hpp"

namespace active {

#if 0
template <typename T>
concept Chronable =
    std::disjunction_v<std::is_same<T, std::chrono::milliseconds>,
                       std::is_same<T, std::chrono::seconds>>;
template <template <typename> typename TList, typename TEvent,
          Chronable TChrono>
inline auto Publish(TChrono delay, TList<TEvent>) {
  etl::singleton<Defer<TEvent>>::create();
  using Type = std::remove_cvref_t<TEvent>;
  constexpr auto defered_work = []() { Type::Publish(); };
  Defer<TEvent>::Publish(delay, defered_work);
}
#endif
} // namespace active